
#pragma once
#include <string>
#include <vector>
#include "cx_sddl.h"

#ifdef _WIN32
#include <Windows.h>
#else
#error("this lib in only for windows")
#endif



namespace CXLib {

	struct _SidInfo {
		std::string sid;
		std::string name;
		std::string domain;
		std::string attrDesc;
		DWORD attr;
	};
	using SidInfo = struct _SidInfo;

	struct _PrivilegeInfo {
    std::string name;
    std::string state;
  };
	using PrivilegeInfo = struct _PrivilegeInfo;

	struct _ProcessTokenInfo {
		DWORD sessionId;
		DWORD tokenIsElevated;
		DWORD integrityLevel;

		SidInfo owner;
		SidInfo user;
		SidInfo primaryGroup;

		std::vector<SidInfo> groups;
		std::vector<PrivilegeInfo> privileges;
		std::vector<CXSddl::AceInfo> daclAces;
	};
	using ProcessTokenInfo = struct _ProcessTokenInfo;

	/// <summary>
	/// Format process token Info
	/// </summary>
	/// <param name="token"></param>
	/// <returns></returns>
	std::string cxFormatProcessTokenInfo(const ProcessTokenInfo& token);

	/// <summary>
	/// Change privilege of process token
	/// </summary>
	/// <param name="hToken"></param>
	/// <param name="lpszPrivilege"></param>
	/// <param name="bEnablePrivilege"></param>
	/// <returns></returns>
	DWORD cxSetPrivilege(
		HANDLE hToken,          // access token handle
		LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
		BOOL bEnablePrivilege   // to enable or disable privilege
	);

	/// <summary>
	/// Get privileges of process token
	/// </summary>
	/// <param name="hToken"></param>
	/// <param name="privileges"></param>
	/// <returns></returns>
	DWORD cxGetTokenPrivileges(HANDLE hToken, std::vector<PrivilegeInfo>& privileges);

	/**
	 * @brief Get the token information of the specified process
	 * @param hProcess hProcess (requires TOKEN-QRY permission)
	 * @param token output parameters, save token related information
	 * @return 0 indicates success, while others are Win32 error codes
	 * @note only supports Windows, the caller needs to ensure that hProcess is valid
	 */
	DWORD cxGetProcessTokenInfo(HANDLE hProcess, ProcessTokenInfo &token);
}
